package com.scriptlib;

import android.graphics.Point;

import java.util.Arrays;


public class GraphicHelper {
    private byte[] screenData;
    private int width = -1;
    private int height = -1;
    private int rowStride = -1;
    private boolean isInit = false;
    private ScreenHelper screenHelper;

    public GraphicHelper(Object obj) {
        screenHelper = new ScreenHelper(obj);
    }

    static public String Version() {
        return "9.19.0";
    }

    //test
    public boolean KeepScreen() {
        if (screenHelper.GetLastFrame()) {
            if (!isInit) {
                isInit = true;
                width = screenHelper.GetWidth();
                height = screenHelper.GetHeight();
                rowStride = width * 4;
            }
            screenData = screenHelper.GetScreenData();
            return true;
        } else {
            return false;
        }
    }

    public byte[] GetScreenData() {
        return screenData;
    }

    public String GetPixelStr(int x, int y) {
        int[] result = GetPixel(x, y);
        int color = (result[0] & 0xff) << 16 | (result[1] & 0xff) << 8 | (result[2] & 0xff);
        return String.format("0x%06x", color);
    }

    public int[] GetPixel(int x, int y) {
        if (x >= 0 && x < width && y >= 0 && y < height) {
            int location = x * 4 + y * rowStride;
            int[] result = new int[3];
            result[0] = screenData[location] & 0xff;
            result[1] = screenData[location + 1] & 0xff;
            result[2] = screenData[location + 2] & 0xff;
            return result;
        } else {
            return new int[]{0, 0, 0};
        }
    }

    public boolean CompareColor(int[] compareColor, int sim, int offset) {
        offset = Math.min(offset, 1);
        int x;
        int y;
        int offsetX = 0;
        int offsetY = 0;
        int size = (offset * 2 + 1) * (offset * 2 + 1);

        int similarity = (int) (255 - 255 * (sim / 100.0));
        int similarity_R = similarity;
        int similarity_G = similarity;
        int similarity_B = similarity;

        if (compareColor.length == 8) {
            similarity_R = similarity + compareColor[5];
            similarity_G = similarity + compareColor[6];
            similarity_B = similarity + compareColor[7];
        }

        for (int i = 0; i < size; i++) {
            x = compareColor[0] + offsetX;
            y = compareColor[1] + offsetY;
            if (x >= 0 && x < width && y >= 0 && y < height) {
                int location = x * 4 + y * rowStride;
                if (Math.abs((screenData[location] & 0xff) - compareColor[2]) <= similarity_R) {
                    if (Math.abs((screenData[location + 1] & 0xff) - compareColor[3]) <= similarity_G) {
                        if (Math.abs((screenData[location + 2] & 0xff) - compareColor[4]) <= similarity_B) {
                            return true;
                        }
                    }
                }
            }

            for (int j = 1; j <= offset; j++) {
                if (offsetX == 0 && offsetY == (-j)) {
                    offsetX += 1;
                } else if (offsetX == j && offsetY == (-j)) {
                    offsetY += 1;
                } else if (offsetX == j && offsetY == j) {
                    offsetX -= 1;
                } else if (offsetX == (-j) && offsetY == j) {
                    offsetY -= 1;
                } else if (offsetX == (-j) && offsetY == (-j - 1)) {
                    offsetX += 1;
                }
            }

        }
        return false;
    }

    private boolean CompareColorEx(int[][] compareColors, int sim, int x, int y, int offset) {
        for (int[] _compareColor : compareColors) {
            int[] compareColor = Arrays.copyOf(_compareColor, _compareColor.length);
            compareColor[0] = compareColor[0] + x;
            compareColor[1] = compareColor[1] + y;
            if (!CompareColor(compareColor, sim, offset)) {
                return false;
            }
        }
        return true;
    }

    public boolean CompareColorEx(int[][] compareColors, int sim, int offset) {
        for (int[] compareColor : compareColors) {
            if (!CompareColor(compareColor, sim, offset)) {
                return false;
            }
        }
        return true;
    }

    public boolean CompareColorExLoop(int[][] compareColors, int sim, int offset, long timeout, long timelag, int sign) throws InterruptedException {
        int num = (int) (timeout / timelag);
        if (sign == 0) {
            for (int i = 0; i < num; i++) {
                if (KeepScreen()) {
                    if (CompareColorEx(compareColors, sim, offset)) {
                        return true;
                    }
                }
                Thread.sleep(timelag);
            }
        } else {
            for (int i = 0; i < num; i++) {
                if (KeepScreen()) {
                    if (!CompareColorEx(compareColors, sim, offset)) {
                        return true;
                    }
                }
                Thread.sleep(timelag);
            }
        }
        return false;
    }

    public Point FindMultiColor(int startX, int startY, int endX, int endY, int[] findColor, int[][] compareColors, int sim, int offset) {
        if (startX < endX && endX < width && startY < endY && endY < height) {
            int similarity = (int) (255 - 255 * (sim / 100.0));
            int similarity_R = similarity;
            int similarity_G = similarity;
            int similarity_B = similarity;
            if (findColor.length == 6) {
                similarity_R = similarity + findColor[3];
                similarity_G = similarity + findColor[4];
                similarity_B = similarity + findColor[5];
            }
            for (int i = startY; i <= endY; i++) {
                int location = startX * 4 + i * rowStride;
                for (int j = startX; j <= endX; j++) {
                    if (Math.abs((screenData[location] & 0xff) - findColor[0]) <= similarity_R) {
                        if (Math.abs((screenData[location + 1] & 0xff) - findColor[1]) <= similarity_G) {
                            if (Math.abs((screenData[location + 2] & 0xff) - findColor[2]) <= similarity_B) {
                                if (CompareColorEx(compareColors, sim, j, i, offset)) {
                                    return new Point(j, i);
                                }
                            }
                        }
                    }
                    location += 4;
                }
            }
        }
        return new Point(-1, -1);
    }

    public Point FindMultiColorLoop(int startX, int startY, int endX, int endY, int[] findColor, int[][] compareColors, int sim, int offset, long timeout, long timelag, int sign) throws InterruptedException {
        int num = (int) (timeout / timelag);
        if (sign == 0) {
            for (int i = 0; i < num; i++) {
                if (KeepScreen()) {
                    Point result = FindMultiColor(startX, startY, endX, endY, findColor, compareColors, sim, offset);
                    if (result.x != -1) {
                        return result;
                    }
                }
                Thread.sleep(timelag);
            }
        } else {
            for (int i = 0; i < num; i++) {
                if (KeepScreen()) {
                    Point result = FindMultiColor(startX, startY, endX, endY, findColor, compareColors, sim, offset);
                    if (result.x == -1) {
                        return result;
                    }
                }
                Thread.sleep(timelag);
            }
        }
        return FindMultiColor(startX, startY, endX, endY, findColor, compareColors, sim, offset);
    }

    public boolean CompareColorExEx(int[][] compareColors, int sim, int x, int y, int offset) {
        for (int[] _compareColor : compareColors) {
            int[] compareColor = Arrays.copyOf(_compareColor, _compareColor.length);
            compareColor[0] = compareColor[0] + x;
            compareColor[1] = compareColor[1] + y;
            // 第5个参数，如果1的话就表示该点匹配上了为真，如果0的话表示该点未匹配上为真
            if ((1 == compareColor[5] && !CompareColor(compareColor, sim, offset))
                    || (0 == compareColor[5] && CompareColor(compareColor, sim, offset))) {
                return false;
            }
        }
        return true;
    }

}
